<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <link href="stable/static/css/site.css" rel="stylesheet" type="text/css">
    <link href="stable/static/css/print.css" rel="stylesheet" type="text/css" media="print">
    <link href="stable/static/css/prettify.css" rel="stylesheet" type="text/css">
    <link href="//www.google.com/images/icons/product/chrome-16.png" rel="icon" type="image/ico">
    <title>Tutorial: OAuth - chrome插件中文开发文档(非官方)</title>
  </head>
  <body>
    <a id="top"></a>
    <div id="header">{Header content}</div>
    <a id="gc-topnav-anchor"></a>
    <div id="gc-topnav">
      <h1>Google Chrome Extensions</h1>
      <ul id="home" class="gc-topnav-tabs">
        <li id="home_link">
          <a href="index.html" title="Google Chrome Extensions home page"><div>Home</div></a>
        </li>
        <li id="docs_link">
          <a href="docs.html" title="Official Google Chrome Extensions documentation"><div>Docs</div></a>
        </li>
        <li id="faq_link">
          <a href="faq.html" title="Answers to frequently asked questions about Google Chrome Extensions"><div>FAQ</div></a>
        </li>
        <li id="samples_link">
          <a href="samples.html" title="Sample Extensions (with source code)"><div>Samples</div></a>
        </li>
        <li id="group_link">
          <a href="http://groups.google.com/a/chromium.org/group/chromium-extensions" title="Google Chrome Extensions developer forum"><div>Group</div></a>
        </li>
        <li id="so_link">
          <a href="http://stackoverflow.com/questions/tagged/google-chrome-extension" title="[google-chrome-extension] tag on Stack Overflow"><div>Questions?</div></a>
        </li>
      </ul>
    </div>
    <div id="gc-container">
      <div id="gc-sidebar">
        <ul 
            class="level1 ">
          <li class="level2">
                <a href="getstarted.html" class="level2 ">Getting Started</a>
          </li>
          <li class="level2">
                <a href="overview.html" class="level2 ">Overview</a>
          </li>
          <li class="level2">
                <a href="whats_new.html" class="level2 ">What's New?</a>
          </li>
          <li class="level2">
                <a href="devguide.html" class="level2 ">Developer's Guide</a>
              <ul 
                  class="level2 ">
                <li class="level3">
                    <a class="button level3">
                      <span class="level3">Browser UI</span>
                      <div class="toggleIndicator level3"></div>
                    </a>
                    <ul toggleable
                        class="level3 hidden">
                      <li class="level4">
                            <a href="browserAction.html" class="level4 ">Browser Actions</a>
                      </li>
                      <li class="level4">
                            <a href="contextMenus.html" class="level4 ">Context Menus</a>
                      </li>
                      <li class="level4">
                            <a href="notifications.html" class="level4 ">Desktop Notifications</a>
                      </li>
                      <li class="level4">
                            <a href="omnibox.html" class="level4 ">Omnibox</a>
                      </li>
                      <li class="level4">
                            <a href="options.html" class="level4 ">Options Pages</a>
                      </li>
                      <li class="level4">
                            <a href="override.html" class="level4 ">Override Pages</a>
                      </li>
                      <li class="level4">
                            <a href="pageAction.html" class="level4 ">Page Actions</a>
                      </li>
                    </ul>
                </li>
                <li class="level3">
                    <a class="button level3">
                      <span class="level3">Browser Interaction</span>
                      <div class="toggleIndicator level3"></div>
                    </a>
                    <ul toggleable
                        class="level3 hidden">
                      <li class="level4">
                            <a href="bookmarks.html" class="level4 ">Bookmarks</a>
                      </li>
                      <li class="level4">
                            <a href="cookies.html" class="level4 ">Cookies</a>
                      </li>
                      <li class="level4">
                            <a href="devtools.html" class="level4 ">Developer Tools</a>
                      </li>
                      <li class="level4">
                            <a href="events.html" class="level4 ">Events</a>
                      </li>
                      <li class="level4">
                            <a href="history.html" class="level4 ">History</a>
                      </li>
                      <li class="level4">
                            <a href="management.html" class="level4 ">Management</a>
                      </li>
                      <li class="level4">
                            <a href="tabs.html" class="level4 ">Tabs</a>
                      </li>
                      <li class="level4">
                            <a href="windows.html" class="level4 ">Windows</a>
                      </li>
                    </ul>
                </li>
                <li class="level3">
                    <a class="button level3">
                      <span class="level3">Implementation</span>
                      <div class="toggleIndicator level3"></div>
                    </a>
                    <ul toggleable
                        class="level3 hidden">
                      <li class="level4">
                            <a href="a11y.html" class="level4 ">Accessibility</a>
                      </li>
                      <li class="level4">
                            <a href="event_pages.html" class="level4 ">Event Pages</a>
                      </li>
                      <li class="level4">
                            <a href="contentSecurityPolicy.html" class="level4 ">Content Security Policy</a>
                      </li>
                      <li class="level4">
                            <a href="content_scripts.html" class="level4 ">Content Scripts</a>
                      </li>
                      <li class="level4">
                            <a href="xhr.html" class="level4 ">Cross-Origin XHR</a>
                      </li>
                      <li class="level4">
                            <a href="i18n.html" class="level4 ">Internationalization</a>
                      </li>
                      <li class="level4">
                            <a href="messaging.html" class="level4 ">Message Passing</a>
                      </li>
                      <li class="level4">
                            <a href="permissions.html" class="level4 ">Optional Permissions</a>
                      </li>
                      <li class="level4">
                            <a href="npapi.html" class="level4 ">NPAPI Plugins</a>
                      </li>
                    </ul>
                </li>
                <li class="level3">
                    <a class="button level3">
                      <span class="level3">Finishing</span>
                      <div class="toggleIndicator level3"></div>
                    </a>
                    <ul toggleable
                        class="level3 hidden">
                      <li class="level4">
                            <a href="hosting.html" class="level4 ">Hosting</a>
                      </li>
                      <li class="level4">
                            <a href="external_extensions.html" class="level4 ">Other Deployment Options</a>
                      </li>
                    </ul>
                </li>
              </ul>
          </li>
          <li class="level2">
                <a href="tutorials.html" class="level2 ">Tutorials</a>
              <ul 
                  class="level2 ">
                <li class="level3">
                      <a href="tut_migration_to_manifest_v2.html" class="level3 ">Manifest V2</a>
                </li>
                <li class="level3">
                      <a href="tut_debugging.html" class="level3 ">Debugging</a>
                </li>
                <li class="level3">
                      <a href="tut_analytics.html" class="level3 ">Google Analytics</a>
                </li>
                <li class="level3">
                      <a  class="level3 selected">OAuth</a>
                </li>
              </ul>
          </li>
          <li class="level2">
                <span class="level2">Reference</span>
              <ul 
                  class="level2 ">
                <li class="level3">
                    <a class="button level3">
                      <span class="level3">Formats</span>
                      <div class="toggleIndicator level3"></div>
                    </a>
                    <ul toggleable
                        class="level3 hidden">
                      <li class="level4">
                            <a href="manifest.html" class="level4 ">Manifest Files</a>
                      </li>
                      <li class="level4">
                            <a href="match_patterns.html" class="level4 ">Match Patterns</a>
                      </li>
                    </ul>
                </li>
                <li class="level3">
                      <a href="permission_warnings.html" class="level3 ">Permission Warnings</a>
                </li>
                <li class="level3">
                      <a href="api_index.html" class="level3 ">chrome.* APIs</a>
                </li>
                <li class="level3">
                      <a href="api_other.html" class="level3 ">Other APIs</a>
                </li>
              </ul>
          </li>
          <li class="level2">
                <span class="level2">More</span>
              <ul 
                  class="level2 ">
                <li class="level3">
                      <a href="http://code.google.com/chrome/webstore/docs/index.html" class="level3 ">Chrome Web Store</a>
                </li>
                <li class="level3">
                      <a href="http://code.google.com/chrome/apps/docs/developers_guide.html" class="level3 ">Hosted Apps</a>
                </li>
                <li class="level3">
                      <a href="themes.html" class="level3 ">Themes</a>
                </li>
              </ul>
          </li>
        </ul>
      </div>
      <div id="gc-pagecontent">
        <h1 class="page_title">Tutorial: OAuth</h1>
        <div id="toc">
          <h2>Contents</h2>
          <ol>
            <li>
              <a href=#requirements>Requirements</a>
            </li>
            <li>
              <a href=#getting-started>Getting started</a>
            </li>
            <li>
              <a href=#oauth-dance>The OAuth dance in an extension</a>
              <ol>
                <li><a href=#set-code>Setup code</a></li><li><a href=#request-token>Fetching and authorizing a request token</a></li><li><a href=#signed-requests>Sending signed API requests</a></li>
              </ol>
            </li>
            <li>
              <a href=#sample-code>Sample code</a>
            </li>
          </ol>
        </div>




<p>
<a href="http://oauth.net/">OAuth</a> is an open protocol that aims to standardize the way desktop and web applications access a user's private data. OAuth provides a mechanism for users to grant access to private data without sharing their private credentials (username/password). Many sites have started enabling APIs to use OAuth because of its security and standard set of libraries.
</p>
<p>
This tutorial will walk you through the necessary steps for creating a Google Chrome Extension that uses OAuth to access an API. It leverages a library that you can reuse in your extensions.
</p>
<p>
This tutorial uses the <a href="http://code.google.com/apis/documents/">Google Documents List Data API</a> as an example OAuth-enabled API endpoint.
</p>

<h2 id="requirements">Requirements</h2>

<p>
This tutorial expects that you have some experience writing extensions for Google Chrome and some familiarity with the <a href="http://code.google.com/apis/accounts/docs/OAuth.html">3-legged OAuth</a> flow. Although you don’t need a background in the <a href="http://code.google.com/apis/documents/">Google Documents List Data API</a> (or the other <a href="http://code.google.com/apis/gdata/">Google Data APIs</a> for that matter), having a understanding of the protocol may be helpful.
</p>

<h2 id="getting-started">Getting started</h2>

<p>
First, copy over the three library files from the Chromium source tree at <a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/oauth_contacts/">.../examples/extensions/oauth_contacts/</a>:
</p>
<ul>
<li><strong><a href="examples/extensions/oauth_contacts/chrome_ex_oauth.html" download="chrome_ex_oauth.html">chrome_ex_oauth.html</a></strong> - interstitial page for the oauth_callback URL</li>
<li><strong><a href="examples/extensions/oauth_contacts/chrome_ex_oauth.js" download="chrome_ex_oauth.js">chrome_ex_oauth.js</a></strong> - core OAuth library</li>
<li><strong><a href="examples/extensions/oauth_contacts/chrome_ex_oauthsimple.js" download="chrome_ex_oauthsimple.js">chrome_ex_oauthsimple.js</a></strong> - helpful wrapper for chrome_ex_oauth.js</li>
</ul>

<p>Place the three library files in the root of your extension directory (or wherever your JavaScript is stored). Then include both .js files in your background page in the following order:</p>

<pre>
&lt;script type="text/javascript" src="chrome_ex_oauthsimple.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="chrome_ex_oauth.js"&gt;&lt;/script&gt;
</pre>

<p>Your background page will manage the OAuth flow.</p>

<h2 id="oauth-dance">The OAuth dance in an extension</h2>

<p>
If you are familiar with the OAuth protocol, you'll recall that the OAuth dance consists of three steps:
</p>

<ol>
<li>fetching an initial request token</li>
<li>having the user authorize the request token</li>
<li>fetching an access token</li>
</ol>

<p>In the context of an extension, this flow gets a bit tricky. Namely, there is no established consumer key/secret between the service provider and the application. That is, there is no web application URL for the user to be redirected to after the approval process.
</p>

<p>
Luckily, Google and a few other companies have been working on an <a href="http://code.google.com/apis/accounts/docs/OAuthForInstalledApps.html">OAuth for installed applications</a> solution that you can use from an extension environment. In the installed applications OAuth dance, the consumer key/secret are ‘anonymous’/’anonymous’ and you provide an <em>application name</em> for the user to grant access to (instead of an application URL). The end result is the same: your background page requests the initial token, opens a new tab to the approval page, and finally makes the asynchronous call for the access token.
</p>

<h3 id="set-code">Setup code</h3>

<p>To initialize the library, create a <code>ChromeExOAuth</code> object in the background page:</p>

<pre>
var oauth = ChromeExOAuth.initBackgroundPage({
  'request_url': &lt;OAuth request URL&gt;,
  'authorize_url': &lt;OAuth authorize URL&gt;,
  'access_url': &lt;OAuth access token URL&gt;,
  'consumer_key': &lt;OAuth consumer key&gt;,
  'consumer_secret': &lt;OAuth consumer secret&gt;,
  'scope': &lt;scope of data access, not used by all OAuth providers&gt;,
  'app_name': &lt;application name, not used by all OAuth providers&gt;
});
</pre>

<p>In the case of the Documents List API and Google’s OAuth endpoints, a possible initialization may be:</p>

<pre>
var oauth = ChromeExOAuth.initBackgroundPage({
  'request_url': 'https://www.google.com/accounts/OAuthGetRequestToken',
  'authorize_url': 'https://www.google.com/accounts/OAuthAuthorizeToken',
  'access_url': 'https://www.google.com/accounts/OAuthGetAccessToken',
  'consumer_key': 'anonymous',
  'consumer_secret': 'anonymous',
  'scope': 'https://docs.google.com/feeds/',
  'app_name': 'My Google Docs Extension'
});
</pre>

<p>
To use the OAuth library,
you must declare the "tabs" permision in the
<a href="http://code.google.com/chrome/extensions/manifest.html">extension manifest</a>.
You must also declare the sites you are using
including the request URL, the authorize URL, access URL,
and, if necessary, the scope URL.
For example:
</p>

<pre>
"permissions": [ "tabs", "https://docs.google.com/feeds/*",
  "https://www.google.com/accounts/OAuthGetRequestToken",
  "https://www.google.com/accounts/OAuthAuthorizeToken",
  "https://www.google.com/accounts/OAuthGetAccessToken"
]
</pre>

<h3 id="request-token">Fetching and authorizing a request token</h3>

<p>
Once you have your background page set up, call the <code>authorize()</code> function to begin the OAuth dance and redirect the user to the OAuth provider. The client library abstracts most of this process, so all you need to do is pass a callback to the <code>authorize()</code> function, and a new tab will open and redirect the user.
</p>

<pre>
oauth.authorize(function() {
  // ... Ready to fetch private data ...
});
</pre>

<p>
You don't need to provide any additional logic for storing the token and secret, as this library already stores these values in the browser’s <code>localStorage</code>. If the library already has an access token stored for the current scope, then no tab will be opened. In either case, the callback will be called.
</p>

<h3 id="signed-requests">Sending signed API requests</h3>

<p>
Once your specified callback is executed, call the <code>sendSignedRequest()</code> function to send signed requests to your API endpoint(s). <code>sendSignedRequest()</code> takes three arguments: a URI, a callback function, and an optional parameter object. The callback is passed two arguments: the response text and the <code>XMLHttpRequest</code> object that was used to make the request.
</p>

<p>This example sends an HTTP <code>GET</code>:</p>

<pre>
function callback(resp, xhr) {
  // ... Process text response ...
};

function onAuthorized() {
  var url = 'https://docs.google.com/feeds/default/private/full';
  var request = {
    'method': 'GET',
    'parameters': {'alt': 'json'}
  };

  // Send: GET https://docs.google.com/feeds/default/private/full?alt=json
  oauth.sendSignedRequest(url, callback, request);
};

oauth.authorize(onAuthorized);
</pre>

<p>A more complex example using an HTTP <code>POST</code> might look like this:</p>

<pre>
function onAuthorized() {
  var url = 'https://docs.google.com/feeds/default/private/full';
  var request = {
    'method': 'POST',
    'headers': {
      'GData-Version': '3.0',
      'Content-Type': 'application/atom+xml'
    },
    'parameters': {
      'alt': 'json'
    },
    'body': 'Data to send'
  };

  // Send: POST https://docs.google.com/feeds/default/private/full?alt=json
  oauth.sendSignedRequest(url, callback, request);
};
</pre>

<p>
By default, the <code>sendSignedRequest()</code> function sends the <code>oauth_*</code> parameters in the URL (by calling <code>oauth.signURL()</code>). If you prefer to send the <code>oauth_*</code> parameters in the <code>Authorization</code> header (or need direct access to the generated header), use <code>getAuthorizationHeader()</code>. Its arguments are a URI, an HTTP method, and an optional object of URL query parameters as key/value pairs.
</p>

<p>Here is the example above using <code>getAuthorizationHeader()</code> and an <code>XMLHttpRequest</code> object:</p>

<pre>
function stringify(parameters) {
  var params = [];
  for(var p in parameters) {
    params.push(encodeURIComponent(p) + '=' +
                encodeURIComponent(parameters[p]));
  }
  return params.join('&');
};

function onAuthorized() {
  var method = 'POST';
  var url = 'https://docs.google.com/feeds/default/private/full';
  var params = {'alt': 'json'};

  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function(data) {
    callback(xhr, data);
  };
  xhr.open(method, url + '?' + stringify(params), true);
  xhr.setRequestHeader('GData-Version', '3.0');
  xhr.setRequestHeader('Content-Type', 'application/atom+xml');
  xhr.setRequestHeader('Authorization', oauth.getAuthorizationHeader(url, method, params));

  xhr.send('Data to send');
};
</pre>

<h2 id="sample-code">Sample code</h2>

<p>
Sample extensions that use these techniques are available in the Chromium source tree:
</p>

<ul>
<li><a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gdocs/">.../examples/extensions/gdocs/</a></li>
<li><a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/oauth_contacts/">.../examples/extensions/oauth_contacts/</a></li>
</ul>
      </div>
    </div>
  </body>
  <script>
    window.bootstrap = {
      api_names: [{"name":"alarms"},{"name":"bookmarks"},{"name":"browserAction"},{"name":"browsingData"},{"name":"commands"},{"name":"contentSettings"},{"name":"contextMenus"},{"name":"cookies"},{"name":"debugger"},{"name":"declarativeWebRequest"},{"name":"devtools.inspectedWindow"},{"name":"devtools.network"},{"name":"devtools.panels"},{"name":"downloads"},{"name":"events"},{"name":"extension"},{"name":"fileBrowserHandler"},{"name":"fontSettings"},{"name":"history"},{"name":"i18n"},{"name":"idle"},{"name":"input.ime"},{"name":"management"},{"name":"omnibox"},{"name":"pageAction"},{"name":"pageCapture"},{"name":"permissions"},{"name":"privacy"},{"name":"proxy"},{"name":"runtime"},{"name":"scriptBadge"},{"name":"storage"},{"name":"tabs"},{"name":"topSites"},{"name":"tts"},{"name":"ttsEngine"},{"name":"types"},{"name":"webNavigation"},{"name":"webRequest"},{"name":"webstore"},{"last":true,"name":"windows"}].concat(
          [{"name":"experimental.bluetooth"},{"name":"experimental.devtools.audits"},{"name":"experimental.devtools.console"},{"name":"experimental.discovery"},{"name":"experimental.identity"},{"name":"experimental.infobars"},{"name":"experimental.offscreenTabs"},{"name":"experimental.processes"},{"name":"experimental.record"},{"name":"experimental.speechInput"},{"name":"experimental.systemInfo.cpu"},{"name":"experimental.systemInfo.storage"},{"last":true,"name":"experimental.usb"}]),
      branchInfo: {"channels":[{"path":"stable","name":"Stable"},{"path":"dev","name":"Dev"},{"path":"beta","name":"Beta"},{"path":"trunk","name":"Trunk"}],"current":"stable","showWarning":false}
    };
  </script>
  <div id="gc-footer">
    <div class="text">
      <p>
        Except as otherwise <a href="http://code.google.com/policies.html#restrictions">noted</a>,
        the content of this page is licensed under the <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
        Attribution 3.0 License</a>, and code samples are licensed under the
        <a rel="license" href="http://code.google.com/google_bsd_license.html">BSD License</a>.
      </p>
      <p>
        ©2012 Google
      </p>
      <script src="stable/static/js/branch.js" type="text/javascript"></script>
      <script src="stable/static/js/sidebar.js" type="text/javascript"></script>
      <script src="stable/static/js/prettify.js" type="text/javascript"></script>
      <script>
        (function() {
          // Auto syntax highlight all pre tags.
          var preElements = document.getElementsByTagName('pre');
          for (var i = 0; i < preElements.length; i++)
            preElements[i].classList.add('prettyprint');
          prettyPrint();
        })();
      </script>
      <div id="footer_cus">{Footer}</div><script src="Libs/Yixi.js"></script><script src="http://s9.cnzz.com/stat.php?id=4928336&web_id=4928336" language="JavaScript"></script>
  
    </div>
  </div>
</html>
